/**
 * pinia 的插件
 *  一、定义插件
 *  二、使用插件
 *
 * 一、定义插件
 *  定义一个函数即可，该函数会收到一个参数context，该参数中包含有很多内容
 *  1. 插件的执行时机，是 store 被组件第一次调用时触发。
 *     多个 store 就会引起插件函数多次触发
 *  2. context 参数的内容
 *    - app     当前项目的 Vue 应用实例
 *    - options 当前作用的仓库定义时所配置的选项
 *    - pinia   项目中的 pinia 实例
 *    - store   当前作用的仓库的实例对象
 *
 *
 * 二、使用插件
 *  pinia实例.use(插件函数)
 */

import { createApp, toRaw } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

/**
 * 定义一个pinia插件
 */
const plugin1 = (context) => {
  // console.log('plugin1', context)
  // 1. 给所有 store 添加 属性与方法
  // return {
  //   a: 1,
  //   b: () => {
  //     console.log('b')
  //   },
  // }

  // 2. 只给 app store 添加
  if (context.store.$id === 'app') {
    return {
      a: 1,
      b: () => {
        console.log('b')
      },
    }
  }
}

/**
 * 定义一个持久化插件
 *  1. 数据的变化，要写入到 localStorage
 *  2. 初始化时，需要从 localStorage 取出数据
 */
const plugin2 = ({ store, options }) => {
  console.log('plugin2 options', store)
  // 要忽略的key集合
  const ignoreKeys = options.ignoreKeys || []

  // 用于存储的key
  const key = store.$id

  // 读取存储，且主动修改store的state数据
  const stateStr = localStorage.getItem(key)
  // 判断是否有值
  if (stateStr) {
    // 解析 stateStr 字符串
    const state = JSON.parse(stateStr)
    // 修改 store state
    store.$patch(state)
  }

  store.$subscribe((mutation, state) => {
    const rawState = JSON.parse(JSON.stringify(state))
    console.log('mutation', rawState)
    // 判断当前 mutation.events.key 是否在 ignoreKeys 中，如果存在则直接 return 不走存储操作
    if (ignoreKeys.includes(mutation.events.key)) return

    ignoreKeys.forEach((key) => {
      delete rawState[key]
    })

    console.log('state', state)

    // 数据变化之后，将最新的数据写入到 本地储存
    localStorage.setItem(key, JSON.stringify(rawState))
  })
}

// 创建应用实例 app
const app = createApp(App)

// 创建 pinia 实例
const pinia = createPinia()

// 注册pinia插件
pinia.use(plugin1).use(plugin2)

// Vue应用实例去注册pinia
app.use(pinia)

// 挂载应用
app.mount('#app')
